package com.itaming.lycheeframework.redis.service;

import com.itaming.lycheeframework.support.utils.*;
import org.springframework.data.redis.core.*;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;

import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Redis操作服务
 *
 * @author A.Ming
 */
public class RedisService {

    private static final long DEFAULT_SCAN_COUNT = 1000;

    private final RedisTemplate<String, Object> redisTemplate;
    private final StringRedisTemplate stringRedisTemplate;
    private final ValueOperations<String, Object> valueOperations;
    private final ListOperations<String, Object> listOperations;
    private final SetOperations<String, Object> setOperations;
    private final ZSetOperations<String, Object> zSetOperations;

    public RedisService(RedisTemplate<String, Object> redisTemplate, StringRedisTemplate stringRedisTemplate) {
        this.redisTemplate = redisTemplate;
        this.stringRedisTemplate = stringRedisTemplate;
        valueOperations = redisTemplate.opsForValue();
        listOperations = redisTemplate.opsForList();
        setOperations = redisTemplate.opsForSet();
        zSetOperations = redisTemplate.opsForZSet();
    }

    // ===== RedisTemplate 相关操作 ===== //

    /**
     * 获取所有符合指定匹配模式的 {@code key}
     *
     * <p>
     * 匹配模式支持 Redis 通配符（*、?、[a-z] 等）
     *
     * <p>
     * 注意：此方法使用 SCAN 实现，避免了 Redis 的阻塞式 KEYS，
     * 在大规模 key 场景下更安全。
     *
     * @param pattern 匹配模式
     * @return 匹配到的 {@code key} 集合，未匹配任何 {@code key} 时返回空集合
     */
    @NonNull
    public Set<String> keys(String pattern) {
        Set<String> keys = new HashSet<>();
        ScanOptions scanOptions = ScanOptions.scanOptions().match(pattern).count(DEFAULT_SCAN_COUNT).build();
        try (Cursor<String> cursor = redisTemplate.scan(scanOptions)) {
            cursor.forEachRemaining(keys::add);
        }
        return keys;
    }

    /**
     * 移动指定的 {@code key} 到指定数据库
     *
     * @param key     key
     * @param dbIndex 数据库索引
     * @return boolean
     */
    public boolean move(String key, int dbIndex) {
        return toPrimitive(redisTemplate.move(key, dbIndex));
    }

    /**
     * 随机返回一个 {@code key}
     *
     * @return 随机的 {@code key} 字符串, 如果 Redis 中无任何 {@code key}，则返回 {@code null}
     */
    public String randomKey() {
        return redisTemplate.randomKey();
    }

    /**
     * 删除一个 {@code key}
     *
     * @param key key
     * @return boolean
     */
    public boolean delete(String key) {
        return toPrimitive(redisTemplate.delete(key));
    }

    /**
     * 删除多个 {@code key}
     *
     * @param keys key列表
     * @return 删除成功的个数
     */
    public long delete(String... keys) {
        return delete(NullSafeUtil.asList(keys));
    }

    /**
     * 删除多个 {@code key}
     *
     * @param keys key集合
     * @return 删除成功的个数
     */
    public long delete(Collection<String> keys) {
        if (CollectionUtil.isEmpty(keys)) {
            return 0;
        }
        return toPrimitiveDefaultZero(redisTemplate.delete(keys));
    }

    /**
     * 删除符合匹配模式的 {@code key}
     *
     * <p>
     * 匹配模式支持 Redis 通配符（*、?、[a-z] 等）
     *
     * @param pattern 匹配模式
     * @return 删除成功的个数
     */
    public long deleteByPattern(String pattern) {
        Set<String> keys = new HashSet<>();
        ScanOptions scanOptions = ScanOptions.scanOptions().match(pattern).count(DEFAULT_SCAN_COUNT).build();
        try (Cursor<String> cursor = redisTemplate.scan(scanOptions)) {
            cursor.forEachRemaining(keys::add);
        }
        return delete(keys);
    }

    /**
     * 判断指定的 {@code key} 是否存在
     *
     * @param key key
     * @return boolean
     */
    public boolean exists(String key) {
        return toPrimitive(redisTemplate.hasKey(key));
    }

    /**
     * 判断任意一个 {@code key} 是否存在
     *
     * @param keys key列表
     * @return boolean
     */
    public boolean existsAny(String... keys) {
        return existsAny(NullSafeUtil.asList(keys));
    }

    /**
     * 判断任意一个 {@code key} 是否存在
     *
     * @param keys key集合
     * @return boolean
     */
    public boolean existsAny(Collection<String> keys) {
        if (CollectionUtil.isEmpty(keys)) {
            return false;
        }

        for (String key : keys) {
            if (exists(key)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断指定的 {@code key} 是否全部存在
     *
     * @param keys key列表
     * @return boolean
     */
    public boolean existsAll(String... keys) {
        return existsAll(NullSafeUtil.asList(keys));
    }

    /**
     * 判断指定的 {@code key} 是否全部存在
     *
     * @param keys key集合
     * @return boolean
     */
    public boolean existsAll(Collection<String> keys) {
        if (CollectionUtil.isEmpty(keys)) {
            return false;
        }

        for (String key : keys) {
            if (!exists(key)) {
                return false;
            }
        }

        return true;
    }

    /**
     * 判断指定的 {@code key} 是否全部不存在
     *
     * @param keys key列表
     * @return boolean
     */
    public boolean existsNone(String... keys) {
        return existsNone(NullSafeUtil.asList(keys));
    }

    /**
     * 判断指定的 {@code key} 是否全部不存在
     *
     * @param keys key列表
     * @return boolean
     */
    public boolean existsNone(Collection<String> keys) {
        return !existsAny(keys);
    }

    /**
     * 设置 {@code key} 的过期时间
     *
     * @param key            key
     * @param timeoutSeconds 过期时间(秒)
     * @return boolean
     */
    public boolean expire(String key, long timeoutSeconds) {
        return expire(key, timeoutSeconds, TimeUnit.SECONDS);
    }

    /**
     * 设置 {@code key} 的过期时间
     *
     * @param key      key
     * @param timeout  过期时间
     * @param timeUnit 时间单位
     * @return boolean
     */
    public boolean expire(String key, long timeout, TimeUnit timeUnit) {
        Assert.notNull(timeUnit, "TimeUnit must not be null");
        return toPrimitive(redisTemplate.expire(key, timeout, timeUnit));
    }

    /**
     * 设置 {@code key} 的过期时间
     *
     * @param key     key
     * @param timeout 过期时间
     * @return boolean
     */
    public boolean expire(String key, Duration timeout) {
        return toPrimitive(redisTemplate.expire(key, timeout));
    }

    /**
     * 设置 {@code key} 的过期时间
     *
     * @param key       key
     * @param timestamp 过期时间
     * @return boolean
     */
    public boolean expireAt(String key, Date timestamp) {
        Assert.notNull(timestamp, "Timestamp must not be null");
        return toPrimitive(redisTemplate.expireAt(key, timestamp));
    }

    /**
     * 设置 {@code key} 的过期时间
     *
     * @param key       key
     * @param timestamp 过期时间
     * @return boolean
     */
    public boolean expireAt(String key, Instant timestamp) {
        return toPrimitive(redisTemplate.expireAt(key, timestamp));
    }

    /**
     * 获取 {@code key} 的过期时间
     *
     * @param key key
     * @return 过期时间(秒)
     */
    public long getExpire(String key) {
        return ObjectUtil.toPrimitive(redisTemplate.getExpire(key), -1);
    }

    /**
     * 获取 {@code key} 的过期时间
     *
     * @param key      key
     * @param timeUnit 时间单位
     * @return 过期时间
     */
    public long getExpire(String key, TimeUnit timeUnit) {
        Assert.notNull(timeUnit, "TimeUnit must not be null");
        return ObjectUtil.toPrimitive(redisTemplate.getExpire(key, timeUnit), -1);
    }

    /**
     * 将 {@code key} 设置为永不过期
     *
     * @param key key
     * @return boolean
     */
    public boolean persist(String key) {
        return toPrimitive(redisTemplate.persist(key));
    }

    /**
     * 重命名 {@code oldKey} 为 {@code newKey} ，{@code newKey} 存在时覆盖
     *
     * @param oldKey 旧key
     * @param newKey 新key
     */
    public void rename(String oldKey, String newKey) {
        redisTemplate.rename(oldKey, newKey);
    }

    /**
     * 指定的 {@code newKey} 不存在时，重命名 {@code oldKey} 为新 {@code newKey}
     *
     * @param oldKey 旧key
     * @param newKey 新key
     * @return 新名称存在则返回 {@code false}，否则返回 {@code true}
     */
    public boolean renameIfAbsent(String oldKey, String newKey) {
        return toPrimitive(redisTemplate.renameIfAbsent(oldKey, newKey));
    }

    // ===== ValueOperations 相关操作 ===== //

    /**
     * 获取指定 {@code key} 的值
     *
     * @param key key
     * @return 获取到的值，如果 {@code key} 不存在则返回 {@code null}
     */
    @SuppressWarnings("unchecked")
    public <V> V get(String key) {
        return (V) valueOperations.get(key);
    }

    /**
     * 获取多个 {@code key} 的值
     *
     * @param keys key列表
     * @return 获取到的值列表，如果 {@code keys} 为空或查询结果为 null，则返回空列表
     */
    @NonNull
    public <V> List<V> get(String... keys) {
        return get(NullSafeUtil.asList(keys));
    }

    /**
     * 获取多个 {@code key} 的值
     *
     * @param keys key集合
     * @return 获取到的值列表，如果 {@code keys} 为空或查询结果为 null，则返回空列表
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> List<V> get(Collection<String> keys) {
        if (CollectionUtil.isEmpty(keys)) {
            return Collections.emptyList();
        }
        List<V> result = (List<V>) valueOperations.multiGet(keys);
        return CollectionUtil.emptyIfNull(result);
    }

    /**
     * 获取指定 {@code key} 的值，并设置新值
     *
     * @param key   key
     * @param value 新值
     * @return 旧值
     */
    @SuppressWarnings("unchecked")
    public <V> V getAndSet(String key, Object value) {
        return (V) valueOperations.getAndSet(key, value);
    }

    /**
     * 获取指定 {@code key} 的值，并设置过期时间
     *
     * @param key           key
     * @param timeoutSecond 过期时间(秒)
     * @return 获取到的值
     */
    public <V> V getAndExpire(String key, long timeoutSecond) {
        return getAndExpire(key, timeoutSecond, TimeUnit.SECONDS);
    }

    /**
     * 获取指定 {@code key} 的值，并设置过期时间
     *
     * @param key      key
     * @param timeout  过期时间
     * @param timeUnit 时间单位
     * @return 获取到的值
     */
    @SuppressWarnings("unchecked")
    public <V> V getAndExpire(String key, long timeout, TimeUnit timeUnit) {
        Assert.notNull(timeUnit, "TimeUnit must not be null");
        return (V) valueOperations.getAndExpire(key, timeout, timeUnit);
    }

    /**
     * 获取指定 {@code key} 的值，并设置过期时间
     *
     * @param key     key
     * @param timeout 过期时间
     * @return 获取到的值
     */
    @SuppressWarnings("unchecked")
    public <V> V getAndExpire(String key, Duration timeout) {
        return (V) valueOperations.getAndExpire(key, timeout);
    }

    /**
     * 获取指定 {@code key} 的值，并删除
     *
     * @param key key
     * @return 获取到的值
     */
    @SuppressWarnings("unchecked")
    public <V> V getAndDelete(String key) {
        return (V) valueOperations.getAndDelete(key);
    }


    /**
     * 获取指定 {@code key} 的值，并设置为永不过期
     *
     * @param key key
     * @return 获取到的值
     */
    @SuppressWarnings("unchecked")
    public <V> V getAndPersist(String key) {
        return (V) valueOperations.getAndPersist(key);
    }

    /**
     * 设置指定 {@code key} 的值
     *
     * @param key   key
     * @param value 值
     */
    public void set(String key, Object value) {
        valueOperations.set(key, value);
    }

    /**
     * 设置指定 {@code key} 的值，并设置过期时间
     *
     * @param key           key
     * @param value         值
     * @param timeoutSecond 过期时间(秒)
     */
    public void set(String key, Object value, long timeoutSecond) {
        set(key, value, timeoutSecond, TimeUnit.SECONDS);
    }

    /**
     * 设置指定 {@code key} 的值，并设置过期时间
     *
     * @param key      key
     * @param value    值
     * @param timeout  过期时间
     * @param timeUnit 时间单位
     */
    public void set(String key, Object value, long timeout, TimeUnit timeUnit) {
        Assert.notNull(timeUnit, "TimeUnit must not be null");
        valueOperations.set(key, value, timeout, timeUnit);
    }

    /**
     * 设置指定 {@code key} 的值，并设置过期时间
     *
     * @param key     key
     * @param value   值
     * @param timeout 过期时间
     */
    public void set(String key, Object value, Duration timeout) {
        valueOperations.set(key, value, timeout);
    }

    /**
     * 指定 {@code key} 不存在时，设置提供的值
     *
     * @param key   key
     * @param value 值
     * @return {@code key} 不存在则设置并返回 {@code true}，否则返回 {@code false}
     */
    public boolean setIfAbsent(String key, Object value) {
        return toPrimitive(valueOperations.setIfAbsent(key, value));
    }

    /**
     * 指定 {@code key} 不存在时，设置提供的值，并设置过期时间
     *
     * @param key           key
     * @param value         值
     * @param timeoutSecond 过期时间(秒)
     * @return {@code key} 不存在则设置并返回 {@code true}，否则返回 {@code false}
     */
    public boolean setIfAbsent(String key, Object value, long timeoutSecond) {
        return setIfAbsent(key, value, timeoutSecond, TimeUnit.SECONDS);
    }

    /**
     * 指定 {@code key} 不存在时，设置提供的值，并设置过期时间
     *
     * @param key     key
     * @param value   值
     * @param timeout 过期时间
     * @param unit    时间单位
     * @return {@code key} 不存在则设置并返回 {@code true}，否则返回 {@code false}
     */
    public boolean setIfAbsent(String key, Object value, long timeout, TimeUnit unit) {
        Assert.notNull(unit, "TimeUnit must not be null");
        return toPrimitive(valueOperations.setIfAbsent(key, value, timeout, unit));
    }

    /**
     * 指定 {@code key} 不存在时，设置提供的值，并设置过期时间
     *
     * @param key     key
     * @param value   值
     * @param timeout 过期时间
     * @return {@code key} 不存在则设置并返回 {@code true}，否则返回 {@code false}
     */
    public boolean setIfAbsent(String key, Object value, Duration timeout) {
        return toPrimitive(valueOperations.setIfAbsent(key, value, timeout));
    }

    /**
     * 指定 {@code key} 存在时，设置提供的值
     *
     * @param key   key
     * @param value 值
     * @return {@code key} 存在则设置并返回 {@code true}，否则返回 {@code false}
     */
    public boolean setIfPresent(String key, Object value) {
        return toPrimitive(valueOperations.setIfPresent(key, value));
    }

    /**
     * 指定 {@code key} 存在时，设置提供的值，并设置过期时间
     *
     * @param key           key
     * @param value         值
     * @param timeoutSecond 过期时间(秒)
     * @return {@code key} 存在则设置并返回 {@code true}，否则返回 {@code false}
     */
    public boolean setIfPresent(String key, Object value, long timeoutSecond) {
        return setIfPresent(key, value, timeoutSecond, TimeUnit.SECONDS);
    }

    /**
     * 指定 {@code key} 存在时，设置提供的值，并设置过期时间
     *
     * @param key     key
     * @param value   值
     * @param timeout 过期时间
     * @param unit    时间单位
     * @return {@code key} 存在则设置并返回 {@code true}，否则返回 {@code false}
     */
    public boolean setIfPresent(String key, Object value, long timeout, TimeUnit unit) {
        Assert.notNull(unit, "TimeUnit must not be null");
        return toPrimitive(valueOperations.setIfPresent(key, value, timeout, unit));
    }

    /**
     * 指定 {@code key} 存在时，设置提供的值，并设置过期时间
     *
     * @param key     key
     * @param value   值
     * @param timeout 过期时间
     * @return {@code key} 存在则设置并返回 {@code true}，否则返回 {@code false}
     */
    public boolean setIfPresent(String key, Object value, Duration timeout) {
        return toPrimitive(valueOperations.setIfPresent(key, value, timeout));
    }

    /**
     * 设置多个 {@code key} 的值
     *
     * @param map key-value 映射
     */
    public void set(Map<String, Object> map) {
        if (CollectionUtil.isEmpty(map)) {
            return;
        }
        valueOperations.multiSet(map);
    }

    /**
     * 设置多个 {@code key} 的值，仅当所有 {@code key} 都不存在时才成功
     *
     * @param map key-value 映射
     * @return 全部设置成功或 {@code map} 为空时返回 {@code true}，任意一个 {@code key} 已存在则整体失败，返回 {@code false}
     */
    public boolean setIfAbsent(Map<String, Object> map) {
        if (CollectionUtil.isEmpty(map)) {
            return true;
        }
        return toPrimitive(valueOperations.multiSetIfAbsent(map));
    }

    /**
     * 初始化指定 {@code key} 为计数器，初始值为 {@code 0}
     *
     * @param key key
     */
    public void initCounter(String key) {
        initCounter(key, 0L);
    }

    /**
     * 初始化指定 {@code key} 为计数器，初始值为 {@code initValue}
     *
     * @param key       key
     * @param initValue 初始值
     */
    public void initCounter(String key, Long initValue) {
        stringRedisTemplate.opsForValue().set(key, NumberUtil.toLong(initValue, 0L).toString());
    }

    /**
     * 初始化指定 {@code key} 为计数器，初始值为 {@code initValue}
     *
     * @param key       key
     * @param initValue 初始值
     */
    public void initCounter(String key, Double initValue) {
        stringRedisTemplate.opsForValue().set(key, NumberUtil.toDouble(initValue, 0d).toString());
    }

    /**
     * 指定 {@code key} 不存在时，初始化为计数器，初始值为 {@code 0}
     *
     * @param key key
     */
    public void initCounterIfAbsent(String key) {
        initCounterIfAbsent(key, 0L);
    }

    /**
     * 指定 {@code key} 不存在时，初始化为计数器，初始值为 {@code initValue}
     *
     * @param key       key
     * @param initValue 初始值
     */
    public void initCounterIfAbsent(String key, Long initValue) {
        stringRedisTemplate.opsForValue().setIfAbsent(key, NumberUtil.toLong(initValue, 0L).toString());
    }

    /**
     * 指定 {@code key} 不存在时，初始化为计数器，初始值为 {@code initValue}
     *
     * @param key       key
     * @param initValue 初始值
     */
    public void initCounterIfAbsent(String key, Double initValue) {
        stringRedisTemplate.opsForValue().setIfAbsent(key, NumberUtil.toDouble(initValue, 0d).toString());
    }

    /**
     * 对指定 {@code key} 的数值执行递增操作
     *
     * @param key key
     * @return 递增后的最新值
     */
    public Long increment(String key) {
        return stringRedisTemplate.opsForValue().increment(key);
    }

    /**
     * 对指定 {@code key} 的数值执行递增操作
     *
     * @param key   key
     * @param delta 步长
     * @return 递增后的最新值
     */
    public Long increment(String key, long delta) {
        return stringRedisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 对指定 {@code key} 的数值执行递增操作
     *
     * @param key   key
     * @param delta 步长
     * @return 递增后的最新值
     */
    public Double increment(String key, double delta) {
        return stringRedisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 对指定 {@code key} 的数值执行递减操作
     *
     * @param key key
     * @return 递减后的最新值
     */
    public Long decrement(String key) {
        return stringRedisTemplate.opsForValue().decrement(key);
    }

    /**
     * 对指定 {@code key} 的数值执行递减操作
     *
     * @param key   key
     * @param delta 步长
     * @return 递减后的最新值
     */
    public Long decrement(String key, long delta) {
        return stringRedisTemplate.opsForValue().decrement(key, delta);
    }

    /**
     * 对指定 {@code key} 的数值执行递减操作
     *
     * @param key   key
     * @param delta 步长
     * @return 递减后的最新值
     */
    public Double decrement(String key, double delta) {
        return stringRedisTemplate.opsForValue().increment(key, -delta);
    }

    // ===== HashOperations 相关操作 ===== //

    /**
     * 获取 {@code hash} 指定字段的值
     *
     * @param key   key
     * @param field hash字段
     * @return 值
     */
    public <HV> HV hGet(String key, Object field) {
        HashOperations<String, Object, HV> hashOperations = redisTemplate.opsForHash();
        return hashOperations.get(key, field);
    }

    /**
     * 获取 {@code hash} 多个字段的值
     *
     * @param key    key
     * @param fields hash字段列表
     * @return 值列表
     */
    @NonNull
    public <HV> List<HV> hGet(String key, Object... fields) {
        return hGet(key, NullSafeUtil.asList(fields));
    }

    /**
     * 获取 {@code hash} 多个字段的值
     *
     * @param key    key
     * @param fields hash字段集合
     * @return 值列表
     */
    @NonNull
    public <HV> List<HV> hGet(String key, Collection<Object> fields) {
        if (CollectionUtil.isEmpty(fields)) {
            return Collections.emptyList();
        }
        HashOperations<String, Object, HV> hashOperations = redisTemplate.opsForHash();
        return CollectionUtil.emptyIfNull(hashOperations.multiGet(key, fields));
    }

    /**
     * 设置 {@code hash} 指定字段的值
     *
     * @param key   key
     * @param field 字段
     * @param value 要设置的值
     */
    public void hSet(String key, Object field, Object value) {
        HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
        hashOperations.put(key, field, value);
    }

    /**
     * 设置 {@code hash} 多个字段的值
     *
     * @param key key
     * @param map 要设置的字段和值的映射
     */
    public void hSet(String key, Map<Object, Object> map) {
        HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
        hashOperations.putAll(key, map);
    }

    /**
     * 指定的 {@code hash} 字段不存在时，设置提供的值
     *
     * @param key   key
     * @param field 字段
     * @param value 要设置的值
     * @return 字段不存在时返回false，否则设置值并返回true
     */
    public boolean hSetIfAbsent(String key, Object field, Object value) {
        HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
        return toPrimitive(hashOperations.putIfAbsent(key, field, value));
    }

    /**
     * 删除 {@code hash} 一个或多个字段
     *
     * @param key    key
     * @param fields 字段列表
     * @return 删除成功的个数
     */
    public long hDelete(String key, Object... fields) {
        if (ArrayUtil.isEmpty(fields)) {
            return 0;
        }
        return toPrimitiveDefaultZero(redisTemplate.opsForHash().delete(key, fields));
    }

    /**
     * 删除 {@code hash} 一个或多个字段
     *
     * @param key    key
     * @param fields 字段集合
     * @return 删除成功的个数
     */
    public long hDelete(String key, Collection<Object> fields) {
        return hDelete(key, fields == null ? null : fields.toArray());
    }

    /**
     * 判断指定的 {@code hash} 字段是否存在
     *
     * @param key   key
     * @param field 字段
     * @return boolean
     */
    public boolean hExists(String key, Object field) {
        return toPrimitive(redisTemplate.opsForHash().hasKey(key, field));
    }

    /**
     * 判断任意一个 {@code hash} 字段是否存在
     *
     * @param key    key
     * @param fields 字段列表
     * @return boolean
     */
    public boolean hExistsAny(String key, Object... fields) {
        return hExistsAny(key, NullSafeUtil.asList(fields));
    }

    /**
     * 判断任意一个 {@code hash} 字段是否存在
     *
     * @param key    key
     * @param fields 字段列表
     * @return boolean
     */
    public boolean hExistsAny(String key, Collection<Object> fields) {
        if (CollectionUtil.isEmpty(fields)) {
            return false;
        }

        for (Object field : fields) {
            if (hExists(key, field)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断指定的 {@code hash} 字段是否全部存在
     *
     * @param key    key
     * @param fields 字段列表
     * @return boolean
     */
    public boolean hExistsAll(String key, Object... fields) {
        return hExistsAll(key, NullSafeUtil.asList(fields));
    }

    /**
     * 判断指定的 {@code hash} 字段是否全部存在
     *
     * @param key    key
     * @param fields 字段列表
     * @return boolean
     */
    public boolean hExistsAll(String key, Collection<Object> fields) {
        if (CollectionUtil.isEmpty(fields)) {
            return false;
        }

        for (Object field : fields) {
            if (!hExists(key, field)) {
                return false;
            }
        }

        return true;
    }

    /**
     * 判断指定的 {@code hash} 字段是否全部不存在
     *
     * @param key    key
     * @param fields 字段列表
     * @return boolean
     */
    public boolean hExistsNone(String key, Object... fields) {
        return !hExistsAny(key, fields);
    }

    /**
     * 判断指定的 {@code hash} 字段是否全部不存在
     *
     * @param key    key
     * @param fields 字段列表
     * @return boolean
     */
    public boolean hExistsNone(String key, Collection<Object> fields) {
        return !hExistsAny(key, fields);
    }

    /**
     * 获取 {@code hash} 所有字段
     *
     * @param key key
     * @return 字段列表
     */
    @NonNull
    public <HK> Set<HK> hKeys(String key) {
        HashOperations<String, HK, ?> hashOperations = redisTemplate.opsForHash();
        return hashOperations.keys(key);
    }

    /**
     * 获取 {@code hash} 所有字段值
     *
     * @param key key
     * @return 字段列表
     */
    @NonNull
    public <HV> List<HV> hValues(String key) {
        HashOperations<String, ?, HV> hashOperations = redisTemplate.opsForHash();
        return hashOperations.values(key);
    }

    /**
     * 获取 {@code hash} 所有字段的 {@code key-value} 映射
     *
     * @param key key
     * @return Map
     */
    @NonNull
    public <HK, HV> Map<HK, HV> hEntries(String key) {
        HashOperations<String, HK, HV> hashOperations = redisTemplate.opsForHash();
        return hashOperations.entries(key);
    }

    /**
     * 获取 {@code hash} 的字段数量
     *
     * @param key key
     * @return 字段数量
     */
    public long hSize(String key) {
        return toPrimitiveDefaultZero(redisTemplate.opsForHash().size(key));
    }

    /**
     * 初始化指定 {@code hash} 字段为计数器，初始值为 {@code 0}
     *
     * @param key   key
     * @param field hash字段
     */
    public void hInitCounter(String key, Object field) {
        hInitCounter(key, field, 0L);
    }

    /**
     * 初始化指定 {@code hash} 字段为计数器，初始值为 {@code initValue}
     *
     * @param key       key
     * @param field     hash字段
     * @param initValue 初始值
     */
    public void hInitCounter(String key, Object field, Long initValue) {
        stringRedisTemplate.opsForHash().put(key, field, NumberUtil.toLong(initValue, 0L).toString());
    }

    /**
     * 初始化指定 {@code hash} 字段为计数器，初始值为 {@code initValue}
     *
     * @param key       key
     * @param field     hash字段
     * @param initValue 初始值
     */
    public void hInitCounter(String key, Object field, Double initValue) {
        stringRedisTemplate.opsForHash().put(key, field, NumberUtil.toDouble(initValue, 0d).toString());
    }

    /**
     * 指定 {@code hash} 字段不存在时，初始化为计数器，初始值为 {@code 0}
     *
     * @param key   key
     * @param field hash字段
     */
    public void hInitCounterIfAbsent(String key, Object field) {
        hInitCounterIfAbsent(key, field, 0L);
    }

    /**
     * 指定 {@code hash} 字段不存在时，初始化为计数器，初始值为 {@code initValue}
     *
     * @param key       key
     * @param field     hash字段
     * @param initValue 初始值
     */
    public void hInitCounterIfAbsent(String key, Object field, Long initValue) {
        stringRedisTemplate.opsForHash().putIfAbsent(key, field, NumberUtil.toLong(initValue, 0L).toString());
    }

    /**
     * 指定 {@code hash} 字段不存在时，初始化为计数器，初始值为 {@code initValue}
     *
     * @param key       key
     * @param field     hash字段
     * @param initValue 初始值
     */
    public void hInitCounterIfAbsent(String key, Object field, Double initValue) {
        stringRedisTemplate.opsForHash().putIfAbsent(key, field, NumberUtil.toDouble(initValue, 0d).toString());
    }

    /**
     * 对指定 {@code hash} 字段的数值执行递增操作
     *
     * @param key   key
     * @param field 字段
     * @return 递增后的最新值
     */
    public Long hIncrement(String key, Object field) {
        return hIncrement(key, field, 1);
    }

    /**
     * 对指定 {@code hash} 字段的数值执行递增操作
     *
     * @param key   key
     * @param field 字段
     * @param delta 步长
     * @return 递增后的最新值
     */
    public Long hIncrement(String key, Object field, long delta) {
        HashOperations<String, Object, ?> hashOperations = redisTemplate.opsForHash();
        return hashOperations.increment(key, field, delta);
    }

    /**
     * 对指定 {@code hash} 字段的数值执行递增操作
     *
     * @param key   key
     * @param field 字段
     * @param delta 步长
     * @return 递增后的最新值
     */
    public Double hIncrement(String key, Object field, double delta) {
        HashOperations<String, Object, ?> hashOperations = redisTemplate.opsForHash();
        return hashOperations.increment(key, field, delta);
    }

    /**
     * 对指定 {@code hash} 字段的数值执行递减操作
     *
     * @param key   key
     * @param field 字段
     * @return 递减后的最新值
     */
    public Long hDecrement(String key, Object field) {
        return hDecrement(key, field, 1);
    }

    /**
     * 对指定 {@code hash} 字段的数值执行递减操作
     *
     * @param key   key
     * @param field 字段
     * @param delta 步长
     * @return 递减后的最新值
     */
    public Long hDecrement(String key, Object field, long delta) {
        HashOperations<String, Object, ?> hashOperations = redisTemplate.opsForHash();
        return hashOperations.increment(key, field, -delta);
    }

    /**
     * 对指定 {@code hash} 字段的数值执行递减操作
     *
     * @param key   key
     * @param field 字段
     * @param delta 步长
     * @return 递减后的最新值
     */
    public Double hDecrement(String key, Object field, double delta) {
        HashOperations<String, Object, ?> hashOperations = redisTemplate.opsForHash();
        return hashOperations.increment(key, field, -delta);
    }

    // ===== ListOperations 相关操作 ===== //

    /**
     * 移除列表头部第一个元素
     *
     * @param key key
     * @return 移除的元素
     */
    @SuppressWarnings("unchecked")
    public <V> V lLeftPop(String key) {
        return (V) listOperations.leftPop(key);
    }

    /**
     * 移除列表头部多个元素
     *
     * @param key   key
     * @param count 要移除的元素数量
     * @return 包含移除元素的列表
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> List<V> lLeftPop(String key, int count) {
        return (List<V>) CollectionUtil.emptyIfNull(listOperations.leftPop(key, count));
    }

    /**
     * 将指定元素插入到列表头部
     *
     * @param key     key
     * @param element 要插入的元素
     * @return 列表长度
     */
    public long lLeftPush(String key, Object element) {
        return toPrimitiveDefaultZero(listOperations.leftPush(key, element));
    }

    /**
     * 将多个元素插入到列表头部
     *
     * @param key      key
     * @param elements 要插入的元素列表
     * @return 列表长度
     */
    public long lLeftPush(String key, Object... elements) {
        return toPrimitiveDefaultZero(listOperations.leftPushAll(key, ArrayUtil.emptyIfNull(elements)));
    }

    /**
     * 将多个元素插入到列表头部
     *
     * @param key      key
     * @param elements 要插入的元素集合
     * @return 列表长度
     */
    public long lLeftPush(String key, Collection<Object> elements) {
        return toPrimitiveDefaultZero(listOperations.leftPushAll(key, elements));
    }

    /**
     * 指定列表存在时，将指定元素插入到列表头部
     *
     * @param key     key
     * @param element 要插入的元素
     * @return 列表长度
     */
    public long lLeftPushIfPresent(String key, Object element) {
        return toPrimitiveDefaultZero(listOperations.leftPushIfPresent(key, element));
    }

    /**
     * 移除列表尾部第一个元素
     *
     * @param key key
     * @return 移除的元素
     */
    @SuppressWarnings("unchecked")
    public <V> V lRightPop(String key) {
        return (V) listOperations.rightPop(key);
    }

    /**
     * 移除列表尾部多个元素
     *
     * @param key   key
     * @param count 要移除的元素数量
     * @return 包含移除元素的列表
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> List<V> lRightPop(String key, int count) {
        return (List<V>) CollectionUtil.emptyIfNull(listOperations.rightPop(key, count));
    }

    /**
     * 将指定元素插入到列表尾部
     *
     * @param key     key
     * @param element 要插入的元素
     * @return 列表长度
     */
    public long lRightPush(String key, Object element) {
        return toPrimitiveDefaultZero(listOperations.rightPush(key, element));
    }

    /**
     * 将多个元素插入到列表尾部
     *
     * @param key      key
     * @param elements 要插入的元素列表
     * @return 列表长度
     */
    public long lRightPush(String key, Object... elements) {
        return toPrimitiveDefaultZero(listOperations.rightPushAll(key, ArrayUtil.emptyIfNull(elements)));
    }

    /**
     * 将多个元素插入到列表尾部
     *
     * @param key      key
     * @param elements 要插入的元素集合
     * @return 列表长度
     */
    public long lRightPush(String key, Collection<Object> elements) {
        return toPrimitiveDefaultZero(listOperations.rightPushAll(key, elements));
    }

    /**
     * 指定列表存在时，将指定元素插入到列表尾部
     *
     * @param key     key
     * @param element 要插入的元素
     * @return 列表长度
     */
    public long lRightPushIfPresent(String key, Object element) {
        return toPrimitiveDefaultZero(listOperations.rightPushIfPresent(key, element));
    }

    /**
     * 从列表 {@code sourceKey} 中移除尾部元素，并将其添加到列表 {@code destinationKey} 的头部
     *
     * @param sourceKey      源key
     * @param destinationKey 目标key
     * @return 移除的元素
     */
    @SuppressWarnings("unchecked")
    public <V> V lRightPopLeftPush(String sourceKey, String destinationKey) {
        return (V) listOperations.rightPopAndLeftPush(sourceKey, destinationKey);
    }

    /**
     * 设置列表中指定索引处的元素
     *
     * @param key     key
     * @param index   索引
     * @param element 要设置的元素
     */
    public void lSet(String key, long index, Object element) {
        listOperations.set(key, index, element);
    }

    /**
     * 获取列表指定索引处的元素
     *
     * @param key   key
     * @param index 要查找的索引
     * @return 元素
     */
    @SuppressWarnings("unchecked")
    public <V> V lIndex(String key, long index) {
        return (V) listOperations.index(key, index);
    }

    /**
     * 获取列表指定元素第一次出现处的索引
     *
     * @param key   key
     * @param value 要查找的元素
     * @return 索引
     */
    public long lIndexOf(String key, Object value) {
        Long index = listOperations.indexOf(key, value);
        return ObjectUtil.toPrimitive(index, -1);
    }

    /**
     * 获取列表指定元素最后一次出现处的索引
     *
     * @param key   key
     * @param value 要查找的元素
     * @return 索引
     */
    public long lLastIndexOf(String key, Object value) {
        Long index = listOperations.lastIndexOf(key, value);
        return ObjectUtil.toPrimitive(index, -1);
    }

    /**
     * 获取列表长度
     *
     * @param key key
     * @return 列表长度
     */
    public long lSize(String key) {
        return toPrimitiveDefaultZero(listOperations.size(key));
    }

    /**
     * 修剪列表，只保留列表中指定范围内的元素，移除其余的元素
     *
     * <p>
     * 负数表示从列表尾部开始，如：{@code -1} 表示最后1个元素，{@code -2} 表示倒数第2个元素
     *
     * <p>
     * 如果 {@code start} 大于 {@code end}，则会删除列表
     *
     * @param key   key
     * @param start 起始索引（包含）
     * @param end   结束索引（包含）
     */
    public void lTrim(String key, long start, long end) {
        listOperations.trim(key, start, end);
    }

    /**
     * 获取列表中指定范围内的元素
     *
     * <p>
     * 负数表示从列表尾部开始，如：{@code -1} 表示最后1个元素，{@code -2} 表示倒数第2个元素
     *
     * @param key   key
     * @param start 起始索引（包含）
     * @param end   结束索引（包含）
     * @return 元素列表
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> List<V> lRange(String key, long start, long end) {
        return (List<V>) CollectionUtil.emptyIfNull(listOperations.range(key, start, end));
    }

    /**
     * 从列表中移除指定数量的与给定值相等的元素
     *
     * <p>
     * <ul>
     *     <li>count = 0：移除所有与给定值相等的元素</li>
     *     <li>count > 0：从头部开始，移除count个与给定值相等的元素</li>
     *     <li>count < 0：从尾部开始，移除count个与给定值相等的元素</li>
     * </ul>
     *
     * @param key   key
     * @param count 要移除的元素数量
     * @param value 元素
     * @return 移除成功的个数
     */
    public long lRemove(String key, long count, Object value) {
        return toPrimitiveDefaultZero(listOperations.remove(key, count, value));
    }

    // ===== SetOperations 相关操作 ===== //

    /**
     * 将一个或多个元素添加到集合中
     *
     * @param key      key
     * @param elements 要添加的元素列表
     * @return 添加成功的元素个数
     */
    public long sAdd(String key, Object... elements) {
        return toPrimitiveDefaultZero(setOperations.add(key, ArrayUtil.emptyIfNull(elements)));
    }

    /**
     * 将一个或多个元素添加到集合中
     *
     * @param key      key
     * @param elements 要添加的元素集合
     * @return 添加成功的元素个数
     */
    public long sAdd(String key, Collection<Object> elements) {
        return sAdd(key, elements == null ? null : elements.toArray());
    }

    /**
     * 移除集合中的一个随机元素
     *
     * @param key key
     * @return 移除的元素
     */
    @SuppressWarnings("unchecked")
    public <V> V sPop(String key) {
        return (V) setOperations.pop(key);
    }

    /**
     * 移除集合中的一个或多个元素
     *
     * @param key      key
     * @param elements 要移除的元素列表
     * @return 移除成功的元素数量
     */
    public long sRemove(String key, Object... elements) {
        return toPrimitiveDefaultZero(setOperations.remove(key, elements));
    }

    /**
     * 随机获取集合中的一个元素
     *
     * @param key key
     * @return 元素
     */
    @SuppressWarnings("unchecked")
    public <V> V sRandomMember(String key) {
        return (V) setOperations.randomMember(key);
    }

    /**
     * 随机获取集合中指定数量的元素
     *
     * @param key   key
     * @param count 要获取的元素数量
     * @return 元素列表
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> List<V> sRandomMembers(String key, long count) {
        return (List<V>) CollectionUtil.emptyIfNull(setOperations.randomMembers(key, count));
    }

    /**
     * 获取两个集合的交集
     *
     * @param key      key
     * @param otherKey 其他key
     * @return 包含交集元素的 {@code Set}
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> Set<V> sIntersect(String key, String otherKey) {
        return (Set<V>) CollectionUtil.emptyIfNull(setOperations.intersect(key, otherKey));
    }

    /**
     * 获取多个集合的交集
     *
     * @param key       key
     * @param otherKeys 其他key集合
     * @return 包含交集元素的 {@code Set}
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> Set<V> sIntersect(String key, Collection<String> otherKeys) {
        Set<V> result = (Set<V>) setOperations.intersect(key, CollectionUtil.emptyIfNull(otherKeys));
        return CollectionUtil.emptyIfNull(result);
    }

    /**
     * 获取多个集合的交集
     *
     * @param keys key列表
     * @return 包含交集元素的 {@code Set}
     */
    @NonNull
    public <V> Set<V> sIntersect(String... keys) {
        return sIntersect(NullSafeUtil.asList(keys));
    }

    /**
     * 获取多个集合的交集
     *
     * @param otherKeys key集合
     * @return 包含交集元素的 {@code Set}
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> Set<V> sIntersect(Collection<String> otherKeys) {
        Set<V> result = (Set<V>) setOperations.intersect(CollectionUtil.emptyIfNull(otherKeys));
        return CollectionUtil.emptyIfNull(result);
    }

    /**
     * 获取两个集合的并集
     *
     * @param key      key
     * @param otherKey 其他key
     * @return 包含并集元素的 {@code Set}
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> Set<V> sUnion(String key, String otherKey) {
        return (Set<V>) CollectionUtil.emptyIfNull(setOperations.union(key, otherKey));
    }

    /**
     * 获取多个集合的并集
     *
     * @param key       key
     * @param otherKeys 其他key列表
     * @return 包含并集元素的 {@code Set}
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> Set<V> sUnion(String key, Collection<String> otherKeys) {
        return (Set<V>) CollectionUtil.emptyIfNull(setOperations.union(key, otherKeys));
    }

    /**
     * 获取多个集合的并集
     *
     * @param keys key列表
     * @return 包含并集元素的 {@code Set}
     */
    @NonNull
    public <V> Set<V> sUnion(String... keys) {
        return sUnion(NullSafeUtil.asList(keys));
    }

    /**
     * 获取多个集合的并集
     *
     * @param otherKeys key集合
     * @return 包含并集元素的 {@code Set}
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> Set<V> sUnion(Collection<String> otherKeys) {
        return (Set<V>) CollectionUtil.emptyIfNull(setOperations.union(otherKeys));
    }

    /**
     * 获取两个集合的差集
     *
     * <p>
     * 差集是指第一个集合中存在，而其他集合中不存在的元素。
     *
     * @param key      key
     * @param otherKey 其他key
     * @return 包含差集元素的 {@code Set}
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> Set<V> sDifference(String key, String otherKey) {
        return (Set<V>) CollectionUtil.emptyIfNull(setOperations.difference(key, otherKey));
    }

    /**
     * 获取多个集合的差集
     *
     * <p>
     * 差集是指第一个集合中存在，而其他集合中不存在的元素。
     *
     * @param key       key
     * @param otherKeys 其他key列表
     * @return 包含差集元素的 {@code Set}
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> Set<V> sDifference(String key, Collection<String> otherKeys) {
        return (Set<V>) CollectionUtil.emptyIfNull(setOperations.difference(key, otherKeys));
    }

    /**
     * 获取多个集合的差集
     *
     * <p>
     * 差集是指第一个集合中存在，而其他集合中不存在的元素。
     *
     * @param keys key列表
     * @return 包含差集元素的 {@code Set}
     */
    @NonNull
    public <V> Set<V> sDifference(String... keys) {
        return sDifference(NullSafeUtil.asList(keys));
    }

    /**
     * 获取多个集合的差集
     *
     * <p>
     * 差集是指第一个集合中存在，而其他集合中不存在的元素。
     *
     * @param otherKeys key集合
     * @return 包含差集元素的 {@code Set}
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> Set<V> sDifference(Collection<String> otherKeys) {
        return (Set<V>) CollectionUtil.emptyIfNull(setOperations.difference(otherKeys));
    }

    /**
     * 获取集合中的所有元素
     *
     * @param key key
     * @return 元素列表
     */
    @NonNull
    @SuppressWarnings("unchecked")
    public <V> Set<V> sMembers(String key) {
        return (Set<V>) CollectionUtil.emptyIfNull(setOperations.members(key));
    }

    /**
     * 判断指定的值是否存在于集合中
     *
     * @param key   key
     * @param value 值
     * @return boolean
     */
    public boolean sIsMember(String key, Object value) {
        return toPrimitive(setOperations.isMember(key, value));
    }

    // ===== ZSetOperation 相关操作 ===== //

    /**
     * 将一个元素添加到有序集合中
     *
     * @param key   key
     * @param value 元素
     * @param score 分数
     * @return boolean
     */
    public boolean zAdd(String key, Object value, double score) {
        return toPrimitive(zSetOperations.add(key, value, score));
    }

    /**
     * 指定元素不存在时，添加到有序集合中
     *
     * @param key   key
     * @param value 元素
     * @param score 分数
     * @return 添加的元素
     */
    public boolean zAddIfAbsent(String key, Object value, double score) {
        return toPrimitive(zSetOperations.addIfAbsent(key, value, score));
    }

    /**
     * 将多个元素添加到有序集合中
     *
     * @param key key
     * @param map 元素和分数的映射关系
     * @return 添加的元素数量
     */
    public long zAdd(String key, Map<Object, Double> map) {
        if (CollectionUtil.isEmpty(map)) {
            return 0;
        }

        Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();
        map.forEach((k, v) -> tuples.add(new DefaultTypedTuple<>(k, v)));

        return toPrimitiveDefaultZero(zSetOperations.add(key, tuples));
    }

    /**
     * 将多个元素添加到有序集合中，跳过已存在的元素
     *
     * @param key key
     * @param map 元素和分数的映射关系
     * @return 添加成功的元素个数
     */
    public long zAddIfAbsent(String key, Map<Object, Double> map) {
        if (CollectionUtil.isEmpty(map)) {
            return 0;
        }

        Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();
        map.forEach((k, v) -> tuples.add(new DefaultTypedTuple<>(k, v)));

        return toPrimitiveDefaultZero(zSetOperations.addIfAbsent(key, tuples));
    }

    /**
     * 从有序集合中移除一个或多个元素
     *
     * @param key    key
     * @param values 元素列表
     * @return 移除成功的元素个数
     */
    public long zRemove(String key, Object... values) {
        return toPrimitiveDefaultZero(zSetOperations.remove(key, values));
    }

    /**
     * 获取有序集合（升序）中指定元素的排名
     *
     * <p>
     * 排名从 {@code 0} 开始
     *
     * @param key   key
     * @param value 元素
     * @return 排名
     */
    public Long zRank(String key, Object value) {
        return zSetOperations.rank(key, value);
    }

    /**
     * 获取有序集合（降序）中指定元素的排名
     *
     * <p>
     * 排名从 {@code 0} 开始
     *
     * @param key   key
     * @param value 元素
     * @return 排名
     */
    public Long zReverseRank(String key, Object value) {
        return zSetOperations.reverseRank(key, value);
    }

    /**
     * 设置有序集合中指定元素的分数
     *
     * @param key   key
     * @param value 元素
     * @return 原分数
     */
    public Double zScore(String key, Object value) {
        return zSetOperations.score(key, value);
    }

    /**
     * 获取有序集合中的元素数量
     *
     * @param key key
     * @return 元素数量
     */
    public long zCard(String key) {
        return toPrimitiveDefaultZero(zSetOperations.zCard(key));
    }

    /**
     * 获取有序集合中指定分数范围内的元素数量
     *
     * @param key key
     * @param min 最小分数（包含）
     * @param max 最大分数（包含）
     * @return 元素数量
     */
    public long zCount(String key, double min, double max) {
        return toPrimitiveDefaultZero(zSetOperations.count(key, min, max));
    }

    /**
     * 获取有序集合（升序）中指定排名范围内的元素
     *
     * <p>
     * 排名从 {@code 0} 开始
     *
     * @param key   key
     * @param start 起始排名（包含）
     * @param end   结束排名（包含）
     * @return 获取到的元素集合，未找到时返回空集合
     */
    @NonNull
    public Set<Object> zRange(String key, long start, long end) {
        return CollectionUtil.emptyIfNull(zSetOperations.range(key, start, end));
    }

    /**
     * 获取有序集合（降序）中指定排名范围内的元素
     *
     * <p>
     * 排名从 {@code 0} 开始
     *
     * @param key   key
     * @param start 起始排名（包含）
     * @param end   结束排名（包含）
     * @return 获取到的元素集合，未找到时返回空集合
     */
    @NonNull
    public Set<Object> zReverseRange(String key, long start, long end) {
        return CollectionUtil.emptyIfNull(zSetOperations.reverseRange(key, start, end));
    }

    /**
     * 获取有序集合（升序）中指定分数范围内的元素
     *
     * @param key key
     * @param min 最小分数（包含）
     * @param max 最大分数（包含）
     * @return 获取到的元素集合，未找到时返回空集合
     */
    @NonNull
    public Set<Object> zRangeByScore(String key, double min, double max) {
        return CollectionUtil.emptyIfNull(zSetOperations.rangeByScore(key, min, max));
    }

    /**
     * 获取有序集合（降序）中指定分数范围内的元素
     *
     * @param key key
     * @param min 最小分数（包含）
     * @param max 最大分数（包含）
     * @return 获取到的元素集合，未找到时返回空集合
     */
    @NonNull
    public Set<Object> zReverseRangeByScore(String key, double min, double max) {
        return CollectionUtil.emptyIfNull(zSetOperations.reverseRangeByScore(key, min, max));
    }

    /**
     * 递增有序集合中指定元素的分数
     *
     * @param key   key
     * @param value 元素
     * @param delta 步长
     * @return 递增后的新分数
     */
    public Double zIncrementScore(String key, Object value, double delta) {
        return zSetOperations.incrementScore(key, value, delta);
    }

    /**
     * 减少有序集合指定元素的分数
     *
     * @param key   key
     * @param value 元素
     * @param delta 步长
     * @return
     */
    public Double zDecrementScore(String key, Object value, double delta) {
        return zSetOperations.incrementScore(key, value, -delta);
    }

    /**
     * 转为原始类型
     *
     * @param value 包装类型值
     * @return 原始类型值
     */
    private boolean toPrimitive(Boolean value) {
        return Boolean.TRUE.equals(value);
    }

    /**
     * 转为原始类型
     *
     * @param value 包装类型值
     * @return 原始类型值
     */
    private long toPrimitiveDefaultZero(Long value) {
        return ObjectUtil.toPrimitive(value, 0);
    }

}
